﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using OpenMetaverse;
//using libsecondlife.Packets;

namespace Trim
{
    public partial class FriendsListForm : Form
    {
        public FriendsListForm()
        {
            InitializeComponent();
        }

        private void FriendsListForm_Load(object sender, EventArgs e)
        {
            Program.client.IMForms = new Dictionary<UUID, IMForm>();

            Program.client.SL.Network.OnDisconnected += new OpenMetaverse.NetworkManager.DisconnectedCallback(Network_OnDisconnected);

            Program.client.SL.Friends.OnFriendOnline += new FriendsManager.FriendOnlineEvent(Friends_OnFriendOnline);
            Program.client.SL.Friends.OnFriendOffline += new FriendsManager.FriendOfflineEvent(Friends_OnFriendOffline);
            Program.client.SL.Friends.OnFriendshipResponse += new FriendsManager.FriendshipResponseEvent(Friends_OnFriendshipResponse);
            Program.client.SL.Friends.OnFriendshipTerminated += new FriendsManager.FriendshipTerminatedEvent(Friends_OnFriendshipTerminated);
            Program.client.SL.Friends.OnFriendshipOffered += new FriendsManager.FriendshipOfferedEvent(Friends_OnFriendshipOffered);
            Program.client.SL.Network.RegisterCallback(OpenMetaverse.Packets.PacketType.UUIDNameReply, new NetworkManager.PacketCallback(UUIDNameReplyHandler));

            Program.client.SL.Self.OnInstantMessage += new AgentManager.InstantMessageCallback(Self_OnInstantMessage);

            ShowFriendsList();
        }

        private void FriendsListForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Program.client.SL.Network.Connected)
                Program.client.SL.Network.Logout();
            List<IMForm> forms = new List<IMForm>();
            lock (Program.client.IMForms)
            {
                foreach (KeyValuePair<UUID, IMForm> kvp in Program.client.IMForms)
                    forms.Add(kvp.Value);
            }
            foreach (IMForm form in forms)
                form.Close();
            Program.client.LoginFormInstance.Show();
        }

        private void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
        {
            if (reason != NetworkManager.DisconnectType.ClientInitiated)
            {
                MessageBox.Show(message, "Disconnected");
                BeginInvoke((MethodInvoker)delegate {
                    Close();
                    Program.client.LoginFormInstance.Show();
                });
            }
        }

        private void FriendsList_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
        {
            e.Cancel = true;
        }

        private void ShowFriendsList()
        {
            if (InvokeRequired)
            {
                BeginInvoke((MethodInvoker)delegate { ShowFriendsList(); });
                return;
            }
            FriendsList.Nodes.Clear();
            FriendsList.Nodes.Add("Online", "Online");
            FriendsList.Nodes.Add("Offline", "Offline");
            Program.client.SL.Friends.FriendList.ForEach(delegate(FriendInfo friend)
            {
                string name;
                if (friend.Name == null)
                    name = "waiting (" + friend.UUID.ToString() + ")";
                else
                    name = friend.Name;
                string uuid = friend.UUID.ToString();
                TreeNode node = new TreeNode(name);
                node.Name = uuid;
                if (friend.IsOnline)
                    FriendsList.Nodes["Online"].Nodes.Add(node);
                else
                    FriendsList.Nodes["Offline"].Nodes.Add(node);
                node.EnsureVisible();
            });
        }

        private void Friends_OnFriendOnline(FriendInfo friend)
        {
            ShowFriendsList();
        }

        private void Friends_OnFriendOffline(FriendInfo friend)
        {
            ShowFriendsList();
        }

        private void Friends_OnFriendshipResponse(UUID agentID, string agentName, bool accepted)
        {
            ShowFriendsList();
        }

        private void Friends_OnFriendshipTerminated(UUID agentID, string agentName)
        {
            ShowFriendsList();
        }

        private void Friends_OnFriendshipOffered(UUID agentID, string agentName, UUID imSessionID)
        {

        }

        private void UUIDNameReplyHandler(OpenMetaverse.Packets.Packet packet, Simulator sim)
        {
            // If the newer lib has a callback for when it receives names, this can be removed
            ShowFriendsList();
        }

        private void FriendsList_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Point point = new Point(e.X, e.Y);
                TreeNode node = FriendsList.GetNodeAt(point);
                if (node != null)
                {
                    if (node.Level > 0)
                    {
                        MenuWithFriend.Show(FriendsList, point);
                        FriendsList.SelectedNode = node;
                        return;
                    }
                }
                MenuWithoutFriend.Show(FriendsList, point);
            }
        }

        private void FriendsList_DoubleClick(object sender, EventArgs e)
        {
            if (FriendsList.SelectedNode != null)
            {
                if (FriendsList.SelectedNode.Level > 0)
                {
                    OpenIM(new UUID(FriendsList.SelectedNode.Name), FriendsList.SelectedNode.Text, false);
                }
            }
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UUID uuid = new UUID(FriendsList.SelectedNode.Name);
            string name = FriendsList.SelectedNode.Text;
            DialogResult result = MessageBox.Show("Are you sure you want to remove " + name + " from your friends list?", "Oh!", MessageBoxButtons.YesNo);
            if (result == DialogResult.Yes)
            {
                Program.client.SL.Friends.TerminateFriendship(uuid);
                ShowFriendsList();
            }
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.client.ResidentSearchFormInstance = new ResidentSearchForm();
            Program.client.ResidentSearchFormInstance.Show();
        }

        private void OpenIM(UUID agentid, string agentname, bool group)
        {
            if (!Program.client.IMForms.ContainsKey(agentid))
            {
                Program.client.IMForms.Add(agentid, new IMForm(agentid, agentname, group));
            }
            Program.client.IMForms[agentid].Show();
        }

        private void iMToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (FriendsList.SelectedNode != null)
            {
                if (FriendsList.SelectedNode.Level > 0)
                {
                    OpenIM(new UUID(FriendsList.SelectedNode.Name), FriendsList.SelectedNode.Text, false);
                }
            }
        }

        private void Self_OnInstantMessage(InstantMessage im, Simulator simulator)
        {
            if (im.Dialog != InstantMessageDialog.StartTyping && im.Dialog != InstantMessageDialog.StopTyping)
            {
                BeginInvoke((MethodInvoker)delegate
                {
                    UUID imid;
                    string imname;
                    bool group = (im.GroupIM || (im.Dialog == InstantMessageDialog.SessionSend));
                    if (group)
                    {
                        imid = im.IMSessionID;
                        imname = "Group: " + Utils.BytesToString(im.BinaryBucket);
                    }
                    else
                    {
                        imid = im.FromAgentID;
                        imname = im.FromAgentName;
                    }
                    OpenIM(imid, imname, group);
                    Program.client.IMForms[imid].AddMessage("(" + im.Dialog.ToString() + " IM) " + im.FromAgentName + ": " + im.Message);
                });
            }
        }
    }
}
